Skip to content

Reuse a program's descriptors after another program was drawn. - #435

Closed
SkippySteve wants to merge 1 commit into
NotRexed:mainfrom
SkippySteve:fix/desc-prog
Closed

SkippySteve wants to merge 1 commit into
NotRexed:mainfrom
SkippySteve:fix/desc-prog

Conversation

@SkippySteve

Copy link
Copy Markdown
Contributor

Problem

Steady play on an RTX 2060 SUPER (driver 615.78.08) was about 32 fps, 1425 draws a frame. Replay of one of those frames spent 14.13 ms before the queue submit. The largest piece was descriptors, 4.42 ms. Programs were 1.56 ms and the command recording 3.40 ms. The GPU's own time was 14.8 ms.

A draw kept its descriptors only when it was the same program as the draw before it, with the same bindings. About 7 draws a frame took that path. Binding another program bumped the binding generation even when the textures, uniform buffers and samplers were unchanged, so the set was built again on the way back. There were about 80 uniform updates a frame (56 of them stream copies), not one per draw, so the bindings themselves were mostly stable.

Change

A program's descriptor writes are kept and pushed again when that program is drawn after another one. The push still happens, because the command buffer is holding the other program's set. The following draw of the same program still takes the existing neighbour path and skips the push.

The kept set is dropped when any of these changed:

  • a binding other than which program is current (textures, buffers, handles, pools, push constants)
  • a texture registration, a destroyed texture, or a mirror that replaced a buffer
  • a uniform update that overlaps a range the build read, or a page stamp in one of those ranges
  • the compute grid, for a compute stage
  • the pointer table of a compute, task or mesh stage

RX_VK_NO_DESC_REUSE=1 still builds every draw. Dump, probe and the stats frame do too, and they do not store a set. The frame log gains a line, draws reused a program's descriptors, beside the existing neighbour line.

Why this is safe

A miss rebuilds, which is what every draw did before. A hit restores the writes from the build and repeats the side effects that build had: storage images are marked written, storage buffers the program writes are stamped, and sampled textures are hazarded from whether they are GPU-written now. The recording's upload stream is only appended to until the next recording, and the kept sets are dropped when that recording starts. A masked clear still pushes the whole set again; it does not drop the copy.

Testing

Game-free, the same way CI runs them:

  • python -I -B tests/test_desc_prog.py
  • python -I -B tests/test_same_bind.py
  • python -I -B tests/test_ub_gap.py
  • python -I -B tests/test_ub_memo.py
  • python -I -B tests/test_vertex_bind.py
  • python -I -B tests/test_desc_clock.py
  • python -I -B tests/test_dispatch_clock.py
  • python -I -B tests/test_table_track.py
  • python -I -B tests/test_same_draw.py
  • python -I -B tests/test_same_dyn.py
  • python -I -B tests/test_pass_hazard.py
  • python -I -B tests/test_handle_lookup.py

Negative control: with the source change put aside and the new test kept, tests/test_desc_prog.py failed (descriptors have no generation of their own). Restoring the change made it pass.

This was not playtested, and fps was not remeasured. The numbers above are from a run before this change.

Scope

This does not include the vertex and index bind skip in #423, pipeline manifests, or further submit batching. Happy to rename the log line or split the test if that reads better.

A draw kept descriptors only when it repeated the previous draw's program.
Binding another program dropped them, so almost every draw built its set
again. The set is kept per program and pushed again when that program returns,
unless a binding, a registration, a mirror, or a uniform update it read has
changed.
@NotRexed

NotRexed commented Nov 9, 2026

Copy link
Copy Markdown
Owner

Closing to keep the queue clear — please rebase on current main and reopen; thanks!

@NotRexed NotRexed closed this Nov 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants